﻿# シンガーソングの発音コンバータ。
#   テーブルデータ→エクセル
#

use strict;

use utf8;
use Win32::OLE qw(in with CP_UTF8);
use Win32::OLE::Const 'Microsoft Excel';

use voice_table;

$Win32::OLE::CP = CP_UTF8;

my $TRUE = 1;
my $FALSE = 0;

my $CATEGORY_SIZE = 22;
my $CATEGORY_MAX = $CATEGORY_SIZE - 1;
my @CATEGORY_NUM = (
	202, 19,109, 63, 42,
	 75, 63, 60, 69, 69,
	 69, 78, 45, 54, 45,
	 42, 36, 22,153,194,
	 33,251
);
my %PATH_PREFIX = (
	e => '/src/resource/English/',
	f => '/src/resource/French/',
	g => '/src/resource/German/',
	i => '/src/resource/Italian/',
	s => '/src/resource/Spanish/'
);
my $HIDE_TERM_NUM = 5;

my $SHEET_NAME = "Simpletext";
my $START_ROW = 2;
my $START_COL = "F";
my $START_COL_HIDE = "E";

my $voice_file_name;
my $kaiwa_file_name;
my $open_simple_file_name;
my $hide_simple_file_name;
my ($excel, $open_book, $hide_book);

main();
exit;

#-----------------------------------------------------------
# メイン。
#-----------------------------------------------------------
sub main {
	my @argv = @ARGV;
	my @pokemon;
	my @waza;
	my @other;
	my ($sheet, $row, $col);
	my ($category, $mark, $data);

	if (@argv != 3) {
		usage();
		exit -1;
	}
	$voice_file_name = $argv[1] . $PATH_PREFIX{$argv[0]} . 'singeroyaji.dat';
	$kaiwa_file_name = $argv[1] . $PATH_PREFIX{$argv[0]} . 'kaiwa.dat';
	$open_simple_file_name = $argv[2];
	$argv[2] =~ /(.*)(\.xls)$/i;
	$hide_simple_file_name = $1 . "_hide" . $2;
	if ($argv[0] ne 'e') {
		$START_COL++;
		$START_COL_HIDE++;
	}

	# 発音テーブルを構築する。
	open VOICE, $voice_file_name or die "error: open $voice_file_name\n";
	for my $i (0 .. $CATEGORY_MAX) {
		my $voice_table_name = sprintf("OyajiWordTbl%02d", $i);
		my $reg = qr/$voice_table_name.*=.*/;
		my $found = $FALSE;
		my ($sub, $count);

		while (<VOICE>) {
			if (/$reg/) {
				$found = $TRUE;
				last;
			}
		}
		if (!$found) {
			die "error: not found $voice_table_name\n";
		}
		if ($i == 0 || $i == 21) {
			# ポケモン名。
			$sub = register_voice_no(\@pokemon, $i);
		} elsif ($i == 18 || $i == 19) {
			# わざ名。
			$sub = register_voice_no(\@waza, $i);
		} else {
			$other[$i] = [];
			$sub = register_voice_no_other($other[$i]);
		}

		$count = 0;
		while (<VOICE>) {
			last if (/^\};$/);
			for my $j (0 .. 5) {
				unless (/\{([\d -]+),([\d -]+),([\d -]+),([\d -]+)/g) {
					die "error: format $voice_file_name, line = $.\n";
				}

				$sub->($count, $j) = [$1, $2, $3, $4];
			}
			$count++;
		}
		if ($count != $CATEGORY_NUM[$i]) {
			die "error: format $voice_file_name, category $i num\n";
		}
	}
	close VOICE;

	# excelに張り込むときに、最大の列数を見ているようなので、ダミーで最大空にしておく。
	$data->[0][0] = "";
	for my $j (0 .. 5) {
		$mark->[0][$j] = "";
		$data->[0][$j * $HIDE_TERM_NUM + 1] = "";
		$data->[0][$j * $HIDE_TERM_NUM + 2] = "";
		for my $k (2 .. $HIDE_TERM_NUM - 1) {
			$data->[0][$j * $HIDE_TERM_NUM + $k + 1] = "";
		}
	}
	# エクセルに張り込む。
	$excel = open_excel();
	$open_book = get_book($excel, $open_simple_file_name);
	$sheet = get_sheet($open_book, $SHEET_NAME);
	$category = $sheet->Range("A$START_ROW:" . $sheet->Range("A65536")->End(xlUp)->Address)->{'Value'};
	$row = 0;
	for my $i (0 .. $CATEGORY_MAX) {
		my ($sub, $count, $kind);

		if ($i == 0 || $i == 21) {
			# ポケモン名。
			$kind = \@pokemon;
			$sub = insert_voice($kind);
		} elsif ($i == 18 || $i == 19) {
			# わざ名。
			$kind = \@waza;
			$sub = insert_voice($kind);
		} else {
			$kind = $other[$i];
			$sub = \&insert_voice_other;
		}

		$count = 0;
		while (1) {
			my $value = $category->[$row][0];
			my ($category, $no);

			if ($value eq "") {
				last;
			}
			unless ($value =~ /^Category(\d\d)Strl?(\d+)$/) {
				die "error: format $open_simple_file_name, row = ", $row + $START_ROW, ", $value\n";
			}
			($category, $no) = ($1, $2);
			if ($category != $i) {
				last;
			}
			$sub->($no, $count, $row + $START_ROW, $value);
			for my $j (0 .. 5) {
				our @NO_TO_MARK;

				if (!defined($kind->[$no][$j]) || $kind->[$no][$j][0] == -1) {
					last;
				}
				$mark->[$row][$j] = $NO_TO_MARK[int $kind->[$no][$j][0] / 3];
				$data->[$row][0] = '*';		# １つでも発音があれば、マークする。
				$data->[$row][$j * $HIDE_TERM_NUM + 1] = $mark->[$row][$j];
				$data->[$row][$j * $HIDE_TERM_NUM + 2] = $kind->[$no][$j][0] % 3 + 1;
				for my $k (2 .. $HIDE_TERM_NUM - 1) {
					$data->[$row][$j * $HIDE_TERM_NUM + $k + 1] = $kind->[$no][$j][$k - 1];
				}
			}
			$row++;
			$count++;
		}
		if ($count != $CATEGORY_NUM[$i]) {
			print "log: category $i num = $count($CATEGORY_NUM[$i])\n";
		}
	}
	$col = add_to_str($START_COL, 5);
	$sheet->Range("$START_COL$START_ROW:" . $col . ($row + $START_ROW - 1))->{'Value'} = $mark;
	$open_book->Save();
	$hide_book = get_book($excel, $hide_simple_file_name);
	$sheet = get_sheet($hide_book, $SHEET_NAME);
	$col = add_to_str($START_COL_HIDE, 6 * $HIDE_TERM_NUM);
	$sheet->Range("$START_COL_HIDE$START_ROW:" . $col . ($row + $START_ROW - 1))->{'Value'} = $data;
	$hide_book->Save();
}

#-----------------------------------------------------------
# 使用方法。
#-----------------------------------------------------------
sub usage {
	my $com = $0;
	$com =~ s/.*\\//;

	print STDERR "\n";
	print STDERR "USAGE: $com <LANG> <pm3_euro project path> <simple text excel path>\n";
	print STDERR "LANG:\n";
	print STDERR "    e   - English\n";
	print STDERR "    f   - French\n";
	print STDERR "    g   - German\n";
	print STDERR "    i   - Italian\n";
	print STDERR "    s   - Spanish\n";
}

#-----------------------------------------------------------
# ポケモン名とわざ名に対して、登録する関数。
#-----------------------------------------------------------
sub register_voice_no {
	my ($kind, $category_no) = @_;
	my $no_list = get_no_list(sprintf("KaiwaWordTbl%02d", $category_no));
	my $sub = sub : lvalue {
		my ($count, $no) = @_;

		$kind->[$no_list->[$count]][$no];
	};
	return $sub;
}

#-----------------------------------------------------------
# その他に対して、登録する関数。
#-----------------------------------------------------------
sub register_voice_no_other {
	my ($kind) = @_;
	my $sub = sub : lvalue {
		my ($count, $no) = @_;

		$kind->[$count][$no];
	};
	return $sub;
}

#-----------------------------------------------------------
# ポケモン名とわざ名に対して、エクセルに挿入する。
#-----------------------------------------------------------
sub insert_voice {
	my ($kind) = @_;
	my $sub = sub {
		my ($no, $count, $row, $value) = @_;

		if (!defined($kind->[$no])) {
			my $file = $open_simple_file_name;

			$file =~ s/^.*([^\\\/]+)$/$1/;
			print "log: none number $file, row = $row, $value\n";
		}
	};
	return $sub;
}

#-----------------------------------------------------------
# その他に対して、エクセルに挿入する。
#-----------------------------------------------------------
sub insert_voice_other {
	my ($no, $count, $row, $value) = @_;

	if ($no != $count) {
		die "error: number $open_simple_file_name, row = $row, $value\n";
	}
}

#-----------------------------------------------------------
# 文字のインクリメント加算。
#-----------------------------------------------------------
sub add_to_str {
	my ($str, $add) = @_;

	for my $i (0 .. $add - 1) {
		$str++;
	}

	return $str;
}

#-----------------------------------------------------------
# エクセルオープン。
#-----------------------------------------------------------
sub open_excel {
	my $excel;

	$excel = Win32::OLE->new('Excel.Application');
	if (!defined($excel)) {
		die "error: start Excel\n";
	}
	return $excel;
}

#-----------------------------------------------------------
# エクセルブック取得。
#-----------------------------------------------------------
sub get_book {
	my ($excel, $file_name) = @_;
	my $book;

	$book = $excel->Workbooks->Open($file_name);
	if (!defined($book)) {
		die "error: open $file_name\n";
	}
	return $book;
}

#-----------------------------------------------------------
# エクセルシート取得。
#-----------------------------------------------------------
sub get_sheet {
	my ($book, $sheet_name) = @_;
	my $sheet;

	$sheet = $book->Worksheets($sheet_name);
	if (!defined($sheet)) {
		die "error: get sheet $sheet_name\n";
	}
	return $sheet;
}

#-----------------------------------------------------------
# 番号リスト取得。
#-----------------------------------------------------------
sub get_no_list {
	my ($table_name) = @_;
	my $reg;
	my $found;
	my $count;
	my @table;

	open KAIWA, $kaiwa_file_name or die "error: open $kaiwa_file_name\n";
	$reg = qr/$table_name.*=.*/;

	$found = $FALSE;
	while (<KAIWA>) {
		if (/$reg/) {
			$found = $TRUE;
			last;
		}
	}
	if (!$found) {
		die "error: not found $table_name\n";
	}
	$count = 0;
	while (<KAIWA>) {
		my @no_list;

		last if (/^\};$/);
		chomp;
		s/\s*(.*),\s*$/$1/;
		@no_list = split /,/;
		for my $no (@no_list) {
			$table[$count++] = $no;
		}
	}
	close KAIWA;

	return \@table;
}

#-----------------------------------------------------------
# 終了処理。
#-----------------------------------------------------------
sub END {
	if (defined($open_book)) {
		$open_book->{Saved} = $TRUE;
		$open_book->Close();
	}
	if (defined($excel)) {
		$excel->Quit();
	}
}
